{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Welcome to the Second Lab - Week 1, Day 3\n",
    "\n",
    "Today we will work with lots of models! This is a way to get comfortable with APIs."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"margin: 0; text-align: left; width:100%\">\n",
    "    <tr>\n",
    "        <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
    "            <img src=\"../assets/stop.png\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
    "        </td>\n",
    "        <td>\n",
    "            <h2 style=\"color:#ff7800;\">Important point - please read</h2>\n",
    "            <span style=\"color:#ff7800;\">The way I collaborate with you may be different to other courses you've taken. I prefer not to type code while you watch. Rather, I execute Jupyter Labs, like this, and give you an intuition for what's going on. My suggestion is that you carefully execute this yourself, <b>after</b> watching the lecture. Add print statements to understand what's going on, and then come up with your own variations.<br/><br/>If you have time, I'd love it if you submit a PR for changes in the community_contributions folder - instructions in the resources. Also, if you have a Github account, use this to showcase your variations. Not only is this essential practice, but it demonstrates your skills to others, including perhaps future clients or employers...\n",
    "            </span>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"margin: 0; text-align: left; width:100%\">\n",
    "    <tr>\n",
    "        <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
    "            <img src=\"../assets/exercise.png\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
    "        </td>\n",
    "        <td>\n",
    "            <h2 style=\"color:#ff7800;\">Exercise</h2>\n",
    "            <span style=\"color:#ff7800;\">Which pattern(s) did this use? Try updating this to add another Agentic design pattern.\n",
    "            </span>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ReAct Pattern"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "import io\n",
    "from anthropic import Anthropic\n",
    "from IPython.display import Markdown, display"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Print the key prefixes to help with any debugging\n",
    "\n",
    "openai_api_key = os.getenv('OPENAI_API_KEY')\n",
    "anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')\n",
    "google_api_key = os.getenv('GOOGLE_API_KEY')\n",
    "deepseek_api_key = os.getenv('DEEPSEEK_API_KEY')\n",
    "groq_api_key = os.getenv('GROQ_API_KEY')\n",
    "\n",
    "if openai_api_key:\n",
    "    print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n",
    "else:\n",
    "    print(\"OpenAI API Key not set\")\n",
    "    \n",
    "if anthropic_api_key:\n",
    "    print(f\"Anthropic API Key exists and begins {anthropic_api_key[:7]}\")\n",
    "else:\n",
    "    print(\"Anthropic API Key not set (and this is optional)\")\n",
    "\n",
    "if google_api_key:\n",
    "    print(f\"Google API Key exists and begins {google_api_key[:2]}\")\n",
    "else:\n",
    "    print(\"Google API Key not set (and this is optional)\")\n",
    "\n",
    "if deepseek_api_key:\n",
    "    print(f\"DeepSeek API Key exists and begins {deepseek_api_key[:3]}\")\n",
    "else:\n",
    "    print(\"DeepSeek API Key not set (and this is optional)\")\n",
    "\n",
    "if groq_api_key:\n",
    "    print(f\"Groq API Key exists and begins {groq_api_key[:4]}\")\n",
    "else:\n",
    "    print(\"Groq API Key not set (and this is optional)\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "from openai import OpenAI\n",
    "\n",
    "openai = OpenAI()\n",
    "\n",
    "# Request prompt\n",
    "request = (\n",
    "    \"Please come up with a challenging, nuanced question that I can ask a number of LLMs to evaluate their intelligence. \"\n",
    "    \"Answer only with the question, no explanation.\"\n",
    ")\n",
    "\n",
    "\n",
    "\n",
    "def generate_question(prompt: str) -> str:\n",
    "    response = openai.chat.completions.create(\n",
    "        model='gpt-4o-mini',\n",
    "        messages=[{'role': 'user', 'content': prompt}]\n",
    "    )\n",
    "    question = response.choices[0].message.content\n",
    "    return question\n",
    "\n",
    "def react_agent_decide_model(question: str) -> str:\n",
    "    prompt = f\"\"\"\n",
    "            You are an intelligent AI assistant tasked with evaluating which language model is most suitable to answer a given question.\n",
    "\n",
    "            Available models:\n",
    "            - OpenAI: excels at reasoning and factual answers.\n",
    "            - Claude: better for philosophical, nuanced, and ethical topics.\n",
    "            - Gemini: good for concise and structured summaries.\n",
    "            - Groq: good for creative or exploratory tasks.\n",
    "            - DeepSeek: strong at coding, technical reasoning, and multilingual responses.\n",
    "\n",
    "            Here is the question to answer:\n",
    "            \"{question}\"\n",
    "\n",
    "            ### Thought:\n",
    "            Which model is best suited to answer this question, and why?\n",
    "\n",
    "            ### Action:\n",
    "            Respond with only the model name you choose (e.g., \"Claude\").\n",
    "                \"\"\"\n",
    "\n",
    "    response = openai.chat.completions.create(\n",
    "        model=\"o3-mini\",\n",
    "        messages=[{\"role\": \"user\", \"content\": prompt}]\n",
    "    )\n",
    "    model = response.choices[0].message.content.strip()\n",
    "    return model\n",
    "\n",
    "def generate_answer_openai(prompt):\n",
    "    answer = openai.chat.completions.create(\n",
    "            model='gpt-4o-mini',\n",
    "            messages=[{'role': 'user', 'content': prompt}]\n",
    "        ).choices[0].message.content\n",
    "    return answer\n",
    "\n",
    "def generate_answer_anthropic(prompt):\n",
    "    anthropic = Anthropic(api_key=anthropic_api_key)\n",
    "    model_name = \"claude-3-5-sonnet-20240620\"\n",
    "    answer = anthropic.messages.create(\n",
    "            model=model_name,\n",
    "            messages=[{'role': 'user', 'content': prompt}],\n",
    "            max_tokens=1000\n",
    "        ).content[0].text\n",
    "    return answer\n",
    "\n",
    "def generate_answer_deepseek(prompt):\n",
    "    deepseek = OpenAI(api_key=deepseek_api_key, base_url=\"https://api.deepseek.com/v1\")\n",
    "    model_name = \"deepseek-chat\"    \n",
    "    answer = deepseek.chat.completions.create(\n",
    "            model=model_name,\n",
    "            messages=[{'role': 'user', 'content': prompt}],\n",
    "            base_url='https://api.deepseek.com/v1'\n",
    "        ).choices[0].message.content\n",
    "    return answer\n",
    "\n",
    "def generate_answer_gemini(prompt):\n",
    "    gemini=OpenAI(base_url='https://generativelanguage.googleapis.com/v1beta/openai/',api_key=google_api_key)\n",
    "    model_name = \"gemini-2.0-flash\"\n",
    "    answer = gemini.chat.completions.create(\n",
    "            model=model_name,\n",
    "            messages=[{'role': 'user', 'content': prompt}],\n",
    "        ).choices[0].message.content\n",
    "    return answer\n",
    "\n",
    "def generate_answer_groq(prompt):\n",
    "    groq=OpenAI(base_url='https://api.groq.com/openai/v1',api_key=groq_api_key)\n",
    "    model_name=\"llama3-70b-8192\"\n",
    "    answer = groq.chat.completions.create(\n",
    "            model=model_name,\n",
    "            messages=[{'role': 'user', 'content': prompt}],\n",
    "            base_url=\"https://api.groq.com/openai/v1\"\n",
    "        ).choices[0].message.content\n",
    "    return answer\n",
    "\n",
    "def main():\n",
    "    print(\"Generating question...\")\n",
    "    question = generate_question(request)\n",
    "    print(f\"\\n🧠 Question: {question}\\n\")\n",
    "    selected_model = react_agent_decide_model(question)\n",
    "    print(f\"\\n🔹 {selected_model}:\\n\")\n",
    "    \n",
    "    if selected_model.lower() == \"openai\":\n",
    "        answer = generate_answer_openai(question)\n",
    "    elif selected_model.lower() == \"deepseek\":\n",
    "        answer = generate_answer_deepseek(question)\n",
    "    elif selected_model.lower() == \"gemini\":\n",
    "        answer = generate_answer_gemini(question)\n",
    "    elif selected_model.lower() == \"groq\":\n",
    "        answer = generate_answer_groq(question)\n",
    "    elif selected_model.lower() == \"claude\":\n",
    "        answer = generate_answer_anthropic(question)\n",
    "    print(f\"\\n🔹 {selected_model}:\\n{answer}\\n\")\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"margin: 0; text-align: left; width:100%\">\n",
    "    <tr>\n",
    "        <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
    "            <img src=\"../assets/business.png\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
    "        </td>\n",
    "        <td>\n",
    "            <h2 style=\"color:#00bfff;\">Commercial implications</h2>\n",
    "            <span style=\"color:#00bfff;\">These kinds of patterns - to send a task to multiple models, and evaluate results,\n",
    "            are common where you need to improve the quality of your LLM response. This approach can be universally applied\n",
    "            to business projects where accuracy is critical.\n",
    "            </span>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
